package com.kt.coroutinedemo.utils


import android.util.Log
import com.streamax.app.cqbus.platform.ext.toByteArray
import com.streamax.app.cqbus.platform.ext.toByteArray2
import java.io.ByteArrayOutputStream
import java.math.BigDecimal
import java.nio.charset.Charset
import java.util.*
import kotlin.experimental.and


object PacketUtils {


    /**
     * 设置BCD形式的字符串
     */
//    fun setBcdString(value: String): ByteArray {
//        var temp = value
//        var buffer: ByteArray
//        if ((temp.length % 2) != 0) {
//            temp =  temp.padStart(temp.length + 1, ' ')
//            buffer = ByteArray((temp.length + 1) / 2)
//
//        } else {
//            buffer = ByteArray(temp.length / 2)
//        }
//
//        var i = 0
//        var k = 0
//        while (i < temp.length) {
//            buffer[k] = value.substring(i, (2 * k)+2).toInt(16).toByte()
//            i += 2
//            k++
//        }
//        return buffer
//
//    }


    /**
     * TODO
     *
     * @param buffer
     * @param offset
     * @return
     */
    fun getWord(buffer: ByteArray, offset: Int): Int {
        return (buffer[offset].toInt() shl 8) + buffer[offset + 1]
    }


    /**
     * 获取BCD形式的字符串
     * @param buffer 放数据的数组
     * @param len 数据长度
     **/
//    fun getBcdString(buffer: ByteArray,len: Int): String {
//        var bcd: String = ""
//        for (i in 0 .. buffer.lastIndex) {
//            bcd += String.format("%02X",buffer?.get(i))
//        }
//        //如果长度
//        if(!StringUtil.isEmpty(bcd) && bcd.length < len){
//            bcd = bcd.padStart(len,'0')
//        } else if(!StringUtil.isEmpty(bcd) && bcd.length > len){
//            bcd = bcd.substring(0,len)
//        }
//        return bcd
//    }


    /**
     * 指定编码格式字符串
     * @param buffer
     * @param offset 起始位置索引
     * @param len
     * @param code 编码格式
     * @param value
     */
    fun setStringbyEncoding(buffer: ByteArray, offset: Int, len: Int, code: String, value: String) {
        val charset = Charset.forName(code)
        var sbuf = value?.toByteArray(charset)
        if (sbuf?.size ?: 0 > len) {
            System.arraycopy(sbuf, 0, buffer, offset, len)
        } else {
            System.arraycopy(sbuf, 0, buffer, offset, sbuf?.size ?: 0)
        }
    }

    /**
     * 长度为二的ByteArray
     */
    fun set2Word(buffer: ByteArray, offset: Int, value: Int) {
        buffer[offset] = (value shr 8).toByte() and 0xFF.toByte()
        buffer[offset + 1] = (value.toByte() and 0xFF.toByte())
    }

    fun set2Word(buffer: ByteArray, value: Int) {
        set2Word(buffer, 0, value)
    }

    fun set4word(buffer: ByteArray, offset: Int, value: Int) {
        buffer[offset] = (value shr 24).toByte() and 0xff.toByte()
        buffer[offset + 1] = (value shr 16).toByte() and 0xff.toByte()
        buffer[offset + 2] = (value shr 8).toByte() and 0xff.toByte()
        buffer[offset + 3] = value.toByte() and 0xff.toByte()
    }

    /**
     * TODO
     *
     * @param buffer
     * @param offset
     * @param value
     */
    fun set8word(buffer: ByteArray, offset: Int, value: Long) {
        buffer[offset] = ((value shr 56) and 0xff).toByte()
        buffer[offset + 1] = ((value shr 48) and 0xff).toByte()
        buffer[offset + 2] = ((value shr 40) and 0xff).toByte()
        buffer[offset + 3] = ((value shr 32) and 0xff).toByte()
        buffer[offset + 4] = ((value shr 24) and 0xff).toByte()
        buffer[offset + 5] = ((value shr 16) and 0xff).toByte()
        buffer[offset + 6] = ((value shr 8) and 0xff).toByte()
        buffer[offset + 7] = (value and 0xff).toByte()
    }




    /**
     * 指定编码格式字符串
     * @param buffer
     * @param offset
     * @param len
     * @param code
     * @param value
     */
    fun setString(buffer: ByteArray, offset: Int, len: Int, code: String?, value: String?) {
        val charset = Charset.forName(code)
        var sbuf = value?.toByteArray(charset)
        if (sbuf?.size ?: 0 > len) {
            System.arraycopy(sbuf, 0, buffer, offset, len)
        } else {
            System.arraycopy(sbuf, 0, buffer, offset, sbuf?.size ?: 0)
        }
    }

    fun GetWord(buffer: ByteArray, offset: Int): Int {
        return (buffer[offset].toInt() and 0xFF shl 8) or (buffer[offset + 1].toInt() and 0xFF)
    }


    /// <summary>
    /// 获取BCD形式的字符串
    /// </summary>
    fun getBcdString(buffer: ByteArray, offset: Int, len: Int): String {
        var bcd: String = ""
        for (i in 0 until len) {
            bcd += String.format("%02X", buffer[i + offset])
        }
        return bcd
    }

    /**
     *
     */
    fun getDword(buffer: ByteArray, offset: Int): UInt {
        var result: UInt = (buffer[offset].toUInt() and 0xFFu) shl 24
        result += buffer[offset + 1].toUInt() shl 16
        result += buffer[offset + 2].toUInt() shl 8
        result += buffer[offset + 3].toUInt()
        return result
    }

    /**
     * 拼接所有的ByteArray
     */
    fun bytesMerger(arrayListOf: MutableList<ByteArray>): ByteArray {
        //获取总byteArray的长度
        var totalLen = 0
        arrayListOf.forEach { totalLen += it.size }

        val finalByteArray = ByteArray(totalLen)
        var index: Int = 0
        for (bytes in arrayListOf) {
            System.arraycopy(bytes, 0, finalByteArray, index, bytes.size)
            index += bytes.size
        }
        return finalByteArray
    }


    /**
     * 将String转成BCD码
     *
     * @param s
     * @return
     */
    fun strToBCDBytes(s: String): ByteArray {
        var s = s
        if (s.length % 2 != 0) {
            s = "0$s"
        }
        val baos = ByteArrayOutputStream()
        val cs = s.toCharArray()
        var i = 0
        while (i < cs.size) {
            val high = cs[i].code - 48
            val low = cs[i + 1].code - 48
            baos.write(high shl 4 or low)
            i += 2
        }
        return baos.toByteArray()
    }

    /**
     * 将BCD码转成String
     *
     * @param b
     * @return
     */
    fun bcdToString(b: ByteArray): String {
        val sb = StringBuffer()
        for (i in b.indices) {
            val h = ((b[i].toInt() and 0xff) shr 4) + 48
            sb.append(h.toChar())
            val l = (b[i].toInt() and 0x0f) + 48
            sb.append(l.toChar())
        }
        return sb.toString()
    }

    /**
     * 单个数字转为ByteArray
     * @param num
     */
    fun singleInt2ByteArray(num: Int) = byteArrayOf(num.toByte())

    /**
     * 6字节BCD时间格式
     * @param buffer
     * @param offset
     * @param time
     */
    fun setBCDTime(buffer: ByteArray, offset: Int, time: DateTime) {
        buffer[offset] = time.year.toString().padStart(4, '0').substring(2, 4).toInt(16).toByte()
        buffer[offset + 1] = time.month.toString().toInt(16).toByte()
        buffer[offset + 2] = time.day.toString().toInt(16).toByte()
        buffer[offset + 3] = time.hour.toString().toInt(16).toByte()
        buffer[offset + 4] = time.minute.toString().toInt(16).toByte()
        buffer[offset + 5] = time.second.toString().toInt(16).toByte()
    }

    /**
     * 6字节Byte 时间格式
     * @param buffer
     * @param offset
     * @param time
     */
    fun setTime(buffer: ByteArray, offset: Int, time: DateTime) {
//        buffer[offset] = time.year.toString().padStart(4, '0').substring(2, 4).toByte()
//        buffer[offset + 1] = time.month.toString().toByte()
//        buffer[offset + 2] = time.day.toString().toByte()
//        buffer[offset + 3] = time.hour.toString().toByte()
//        buffer[offset + 4] = time.minute.toString().toByte()
//        buffer[offset + 5] = time.second.toString().toByte()

        buffer[offset] = time.year.toString().padStart(4, '0').substring(2, 4).toInt(16).toByte()
        buffer[offset + 1] = time.month.toString().toInt(16).toByte()
        buffer[offset + 2] = time.day.toString().toInt(16).toByte()
        buffer[offset + 3] = time.hour.toString().toInt(16).toByte()
        buffer[offset + 4] = time.minute.toString().toInt(16).toByte()
        buffer[offset + 5] = time.second.toString().toInt(16).toByte()
    }


    /**
     * TODO 经纬度转换
     *
     * @param buffer
     * @param offset
     * @param value
     */
    fun setCoordinate(buffer: ByteArray, offset: Int, value: Double) {
        try {
            //度
            var degree: Int = value.toInt()
            //分
            var minute: Double = (value - degree) * 60
            //小数点后4位
            var mf: Int = ((minute - minute.toInt()) * 10000).toInt()
            buffer[offset] = (degree and 0xFF).toByte()
            buffer[offset + 1] = (minute.toInt() and 0xFF).toByte()
            buffer[offset + 2] = ((mf / 100) and 0xFF).toByte()
            buffer[offset + 3] = ((mf % 100) and 0xFF).toByte()
        } catch (e: Exception) {
            e.printStackTrace();
        }
    }


    /**
     * TODO 海拔高度
     *
     * @param buffer
     * @param offset
     * @param value
     */
    fun setAltitude(buffer: ByteArray, offset: Int, value: UShort) {
        buffer[offset] = (value / 100u).toByte()
        buffer[offset + 1] = (value % 100u).toByte()
    }

    /**
     * TODO 设置方向(3位)
     *
     * @param buffer
     * @param offset
     * @param value
     */
    fun setAngle(buffer: ByteArray, offset: Int, value: BigDecimal) {
        val lval = value.toInt()
        buffer[offset] = (lval / 100).toByte()
        buffer[offset + 1] = (lval % 100).toByte()
        buffer[offset + 2] = ((value * BigDecimal(100)) % BigDecimal(100)).toByte()
    }

    fun setAngle(buffer: ByteArray, offset: Int, value: Double) {
        val lval = value.toInt()
        buffer[offset] = (lval / 100).toByte()
        buffer[offset + 1] = (lval % 100).toByte()
        buffer[offset + 2] = ((value * 100).toLong() % 100).toByte()
    }

    /**
     * TODO 里程
     *
     * @param buffer
     * @param offset
     * @param value
     */
    fun setMileage(buffer: ByteArray, offset: Int, value: BigDecimal) {
        val lval = value.toLong()
        buffer[offset] = (lval / 100).toByte()
        buffer[offset + 1] = (lval % 100).toByte()
        buffer[offset + 2] = (value * BigDecimal(100) % BigDecimal(100)).toByte()
    }

    /**
     * TODO 里程
     *
     * @param buffer
     * @param offset
     * @param value
     */
    fun setMileage(buffer: ByteArray, offset: Int, value: Float) {
        val lval = value.toLong()
        buffer[offset] = (lval / 100).toByte()
        buffer[offset + 1] = (lval % 100).toByte()
        buffer[offset + 2] = ((value * 100).toLong() % 100).toByte()
    }

    /**
     * TODO 里程
     *
     * @param buffer
     * @param offset
     * @param value
     */
    fun setMileage(buffer: ByteArray, value: Float) {
        val lval = value.toLong()
        val offset = 0
        buffer[offset] = (lval / 100).toByte()
        buffer[offset + 1] = (lval % 100).toByte()
        buffer[offset + 2] = ((lval * 100) % 100).toByte()
    }


    /**
     * TODO 设置报警状态
     *
     * @param buffer
     * @param offset
     * @param value
     */
    fun setAlartStatus(buffer: ByteArray, offset: Int, value: Int) {
        buffer[offset] = (value and 0x0F).toByte()
        buffer[offset + 1] = ((value shr 8) and 0x0F).toByte()
        buffer[offset + 2] = ((value shr 16) and 0x0F).toByte()
        buffer[offset + 3] = ((value shr 24) and 0x0F).toByte()
    }

    /**
     * TODO fload转4位
     *
     * @param buffer
     * @param offset
     * @param value
     */
    fun setDword(buffer: ByteArray, offset: Int, value: Float) {
        buffer[offset] = ((value.toInt() shr 24) and 0xff).toByte()
        buffer[offset + 1] = (value.toInt() shr 16 and 0xff).toByte()
        buffer[offset + 2] = (value.toInt() shr 8 and 0xff).toByte()
        buffer[offset + 3] = (value.toInt() and 0xff).toByte()
    }

    /**
     * 字符串转ByteArray
     */
    fun string2ByteArray(str: String) = str.toByteArray()


    /**
     * 封装kt2626协议
     * @param command 命令
     * @param len 计算数据长度
     */
    fun basePackage(command: Byte, content: ByteArray): ByteArray {
        var length = content.size
        var len = 11 + length
        val buffer = ByteArray(len) // 创建长度为10的byte数组，默认初始化为0
        var offset = 0;
        //头部
        buffer[offset] = 0x26;
        buffer[offset + 1] = 0x26;
        offset += 2;
        //命令ID
        buffer[offset] = command;
        offset += 1;
        //长度
        buffer[offset] = (((len - 5) ushr 8) and 0xFF).toByte() //(len - 5).toByte();
        buffer[offset + 1] = ((len - 5) and 0xFF).toByte();//这里需要测试
        offset += 2;
        //获取vip
        var vip = byteArrayOf(22,29, 227.toByte(), 226.toByte())
        //VIP
        if (vip.size != 4) {
            return ByteArray(0)
        }
        System.arraycopy(vip, 0, buffer, offset, 4)
        offset += 4;
        //内容
        if (length > 0) {
            System.arraycopy(
                content,
                0,
                buffer,
                offset,
                length
            ) // 从source的第1个元素开始，复制3个元素到destination的前3个位置
            offset += length;
        }
        //校验
        buffer[offset] = XorValue(buffer, 0, len - 2);
        offset += 1;
        //尾部
        buffer[offset] = 0x0B;
        offset += 1;

        return buffer;
    }

    /**
     * 按字节计算校验值
     * 数据缓存
     * @param offset 起始字节
     * @param len 计算数据长度
     */
    fun XorValue(buffer: ByteArray, offset: Int, len: Int): Byte {
        var byteValue: Byte = 0
        for (i in 0..len) {
            // 在Kotlin中的等价实现
            byteValue = (byteValue.toInt() xor buffer[offset + i].toInt()).toByte()
        }
        return byteValue;
    }

    /**
     * 长星LED校验和
     */
    fun XorValueLED(buffer: ByteArray):Byte{
        var byteValue: Byte = 0
        for (i in 0 until buffer.size-1){
          byteValue =  ( buffer[i].toInt() xor  buffer[i+1].toInt()).toByte()
        }
        return byteValue
    }

    /**
     * TODO 清理byteArray里的空数据
     *
     * @param array
     * @return
     */
    fun trimTrailingZeros(array: ByteArray): ByteArray {
        for (i in array.size - 1 downTo 0) {
            if (array[i] != 0.toByte()) {
                return array.sliceArray(0 until i + 1)
            }
        }
        return byteArrayOf() // 全部是0的情况
    }

    /**
     * 文件下载基础封包
     *
     * @param command 文件下载命令ID
     * @param downSnNum 序号
     * @param content 数据
     */
    fun baseFilePacket(command: Byte, downSnNum: Int, content: ByteArray): ByteArray {
        var length = content.size
        var len = 15 + length
        val buffer = ByteArray(len) // 创建byte数组，默认初始化为0
        var offset = 0
        //头部
        buffer[offset] = 0x26
        buffer[offset + 1] = 0x26
        offset += 2
        //命令ID
        buffer[offset] = command;
        offset += 1
        //长度
        buffer[offset] = (((len - 5) ushr 8) and 0xFF).toByte()
        buffer[offset + 1] = ((len - 5) and 0xFF).toByte();//这里需要测试
        offset += 2
        //获取终端号
        var termianlno = byteArrayOf(0x00,0x33,0x00,0x00,0x08,0x09)
        //VIP
        if (termianlno.size != 6) {
            return ByteArray(0)
        }
        System.arraycopy(termianlno, 0, buffer, offset, 6)
        offset += 6
        //序列号
        var snNumByte = downSnNum.toByteArray2
        System.arraycopy(snNumByte, 0, buffer, offset, 2)
        offset += 2
        //内容
        if (length > 0) {
            System.arraycopy(
                content,
                0,
                buffer,
                offset,
                length
            ) // 从source的第1个元素开始，复制3个元素到destination的前3个位置
            offset += length;
        }
        //校验
        buffer[offset] = XorValue(buffer, 0, len - 2);
        offset += 1;
        //尾部
        buffer[offset] = 0x0B;
        offset += 1;

        return buffer
    }




    /**
     * 获取开投LED时间同步的数据
     */
     fun getSyncTimeData(): ByteArray {
        val calendar = Calendar.getInstance()
        val year = calendar[Calendar.YEAR]
        var month = calendar[Calendar.MONTH]
        month += 1 // Calendar.MONTH 从0开始计数
        val day = calendar[Calendar.DAY_OF_MONTH]
        val hour = calendar[Calendar.HOUR_OF_DAY]
        val minute = calendar[Calendar.MINUTE]
        val second = calendar[Calendar.SECOND]
        var dayOfWeek = calendar[Calendar.DAY_OF_WEEK]
        val stringBuffer = StringBuffer()
        var dateString = ""

        stringBuffer.append(year)
        if (month < 10) {
            stringBuffer.append("0").append(month)
        } else {
            stringBuffer.append(month)
        }

        if (day < 10) {
            stringBuffer.append("0").append(day)
        } else {
            stringBuffer.append(day)
        }
//        dateString = stringBuffer.toString()


//        val timeString = StringBuffer()
        if (hour < 10) {
            stringBuffer.append("0")
        }
        stringBuffer.append(hour)

        if (minute < 10) {
            stringBuffer.append("0")
        }
        stringBuffer.append(minute)

        if (second < 10) {
            stringBuffer.append("0")
        }
        stringBuffer.append(second)


        dayOfWeek = if (dayOfWeek == 0) {
            7
        } else {
            dayOfWeek - 1
        }
        stringBuffer.append("0")
        stringBuffer.append(dayOfWeek)
        Log.e(PacketUtils::class.simpleName, "时间====${stringBuffer.toString()}")
//        val date = BCDUtils.str2Bcd(dateString)
//        val time = BCDUtils.str2Bcd(timeString.toString())
//        val week = byteArrayOf(dayOfWeek.toByte())
//        var result = mutableListOf<ByteArray>().apply {
//            add(0,date)
//            add(1,time)
//            add(2,week)
//        }

        return  BCDUtils.str2Bcd(stringBuffer.toString())
    }
}